package com.resto.scm.web.service.impl;

import cn.restoplus.common.utils.DateUtil;
import cn.restoplus.common.utils.log.LogBetter;
import cn.restoplus.common.utils.log.LogLevel;
import cn.restoplus.rpc.server.RpcService;
import com.resto.scm.web.conmmon.KeyPrefix;
import com.resto.scm.web.dao.DocStkInPlanHeaderDao;
import com.resto.scm.web.dto.DocStockCountDetailDo;
import com.resto.scm.web.dto.DocStockCountHeaderDo;
import com.resto.scm.web.dto.DocStockInput;
import com.resto.scm.web.dto.MaterialStockDo;
import com.resto.scm.web.enums.MaterialTypeStatus;
import com.resto.scm.web.exception.ScmServiceException;
import com.resto.scm.web.keygenerate.UniqueCodeGenerator;
import com.resto.scm.web.manager.DocMaterialStockManager;
import com.resto.scm.web.manager.DocStockCountDetailManager;
import com.resto.scm.web.manager.DocStockCountHeaderManager;
import com.resto.scm.web.model.DocMaterialStock;
import com.resto.scm.web.model.DocStockCountDetail;
import com.resto.scm.web.model.DocStockCountHeader;
import com.resto.scm.web.service.ArticleSaleService;
import com.resto.scm.web.service.StockCountCheckService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.*;

import static cn.restoplus.common.tracelog.TraceLoggerFactory.logger;


/**
 * 库存盘点管理
 */

@RpcService
public class StockCountCheckServiceImpl implements StockCountCheckService {

    @Autowired
    private DocStockCountDetailManager docStockCountDetailManager;
    @Autowired
    private DocStockCountHeaderManager docStockCountHeaderManager;
    @Autowired
    private DocMaterialStockManager docMaterialStockManager;
    @Autowired
    private DocStkInPlanHeaderDao docStkInPlanHeaderDao;
    @Autowired
    private ArticleSaleService articleSaleService;

    private String countMaterialTypes(List<DocStockCountDetailDo> list) {
        Set<String> sets = new HashSet<>();
        for (DocStockCountDetailDo docStockCountDetailDo:list) {
            Arrays.stream(MaterialTypeStatus.values()).forEach((MaterialTypeStatus item) ->{
                if(docStockCountDetailDo.getMaterialType() != null &&
                        docStockCountDetailDo.getMaterialType().equals(item.getValue())) {
                    sets.add(item.getDescription());
                }
            });
        }
        return String.join(",", sets);
    }

    @Override
    public List<DocStockCountHeaderDo> findStockList(String shopId) {
//        List<DocStockCountHeaderDo> list = JSON.parseArray(toJSONString(docStockCountHeaderManager.findStockList(shopId),
//                SerializerFeature.WriteMapNullValue),DocStockCountHeaderDo.class);
        List<DocStockCountHeaderDo> list = docStockCountHeaderManager.findStockList(shopId);
        for (DocStockCountHeaderDo item : list){
            item.setSize(item.getStockCountDetailList().size());
            item.setMaterialType(countMaterialTypes(item.getStockCountDetailList()));
        }
        return list;
    }

    @Override
    public boolean saveStock(DocStockInput docStockInput) {

        if (null == docStockInput) {
            throw new ScmServiceException("SCM 新增盘点单为空");
        }
        if (docStockInput.getDocStockCountDetailDo().isEmpty()){
            throw new ScmServiceException("SCM 新增盘点单明细为空");
        }

        //统计本次所有要参与盘点的原料id
        List<Long> materialStockCodeAlls = new ArrayList<>(docStockInput.getDocStockCountDetailDo().size());
        //统计本次参与盘点失败的原料id
        List<Long> materialStockCodeFails = new ArrayList<>(docStockInput.getDocStockCountDetailDo().size());

        try {
            //先保存盘点单
            DocStockCountHeader docStockCountHeader = new DocStockCountHeader();
            docStockCountHeader.setGmtCreate(new Date());
            docStockCountHeader.setCreaterId(docStockInput.getCreateId());
            docStockCountHeader.setCreaterName(docStockInput.getCreateName());
            String headerCode = UniqueCodeGenerator.generate(KeyPrefix.SCH.getPrefix(), "D");
            docStockCountHeader.setOrderCode(headerCode);
            docStockCountHeader.setOrderName(docStockInput.getOrderName());
            docStockCountHeader.setStockCountStartTime(DateUtil.parseDate(docStockInput.getStartTime(),DateUtil.DEF_PATTERN));
            docStockCountHeader.setStockCountEndTime(DateUtil.parseDate(docStockInput.getEndTime(),DateUtil.DEF_PATTERN));
            docStockCountHeader.setShopDetailId(docStockInput.getShopId());
            docStockCountHeader.setPublishedTime(new Date());
            docStockCountHeader.setIsBlind(1);
            docStockCountHeader.setOrderStatus("11");
            docStockCountHeaderManager.insertOrUpdate(docStockCountHeader);

            String lastCountTime =docStockCountHeaderManager.findLastStockCountOfTime(docStockInput.getShopId());
            if (StringUtils.isBlank(lastCountTime)){
                String stkBeginTime = docStkInPlanHeaderDao.findMinBeginTime(docStockInput.getShopId());
                if (StringUtils.isBlank(stkBeginTime)){
                    lastCountTime = DateUtil.getCurrentDateTime();
                }else {
                    lastCountTime = stkBeginTime;
                }
            }
            Map<Long, Map<String, BigDecimal>> stockBurn =articleSaleService.countMaterialStockSellGroupByMaterialId(docStockInput.getShopId(), lastCountTime);
            //再保存盘点单详情
            for (DocStockCountDetailDo item : docStockInput.getDocStockCountDetailDo()){
                materialStockCodeAlls.add(item.getMaterialId());
                DocMaterialStock docMaterialStock = docMaterialStockManager.findStockByShopId(docStockInput.getShopId(),item.getMaterialId());
                try {
                        if(docMaterialStock == null){
                            LogBetter.instance(logger)
                                    .setLevel(LogLevel.INFO)
                                    .setMsg("[SCM-查询盘点单信息]")
                                    .addParm("shopId:", docStockInput.getShopId())
                                    .addParm("materialId:", item.getMaterialId())
                                    .log();
                            throw new ScmServiceException("该原料，库存不存在");
                        }else {
                            DocStockCountDetail docStockCountDetail = new DocStockCountDetail();
                            docStockCountDetail.setStockCountHeaderId(docStockCountHeader.getId());
                            docStockCountDetail.setStockCountHeaderCode(headerCode);
                            docStockCountDetail.setActStockCount(item.getActStockCount());
                            docStockCountDetail.setMaterialId(item.getMaterialId());
                            docStockCountDetail.setDefferentReason(item.getDefferentReason());
                            if (stockBurn.get(item.getMaterialId()) != null){
                                docStockCountDetail.setTheoryStockCount(docMaterialStock.getActStockCount().subtract(stockBurn.get(item.getMaterialId()).get(ArticleSaleService.materialTotalCount)));
                            }else {
                                docStockCountDetail.setTheoryStockCount(new BigDecimal(0));
                            }
                            docStockCountDetail.setGmtCreate(new Date());
                            docStockCountDetail.setCreaterId(docStockInput.getCreateId());
                            docStockCountDetail.setCreaterName(docStockInput.getCreateName());
                            docStockCountDetailManager.insert(docStockCountDetail);
                            docMaterialStockManager.updateMaterStock(item,docStockInput);
                        }

                 }catch (Exception e){
                    LogBetter.instance(logger)
                            .setLevel(LogLevel.INFO)
                            .setMsg("[SCM-新增盘点单明细失败]")
                            .addParm("失败盘点单明细id信息",item.getMaterialId())
                            .addParm("shopId:",docStockInput.getShopId())
                            .log();
                    materialStockCodeFails.add(item.getMaterialId());
                    throw new ScmServiceException("新增盘点单明细失败"+item.getMaterialId());
                 }
            }
        }catch (Exception e){
            LogBetter.instance(logger)
                    .setLevel(LogLevel.INFO)
                    .setMsg("[SCM-新增盘点单失败]")
                    .addParm("失败盘点单信息", docStockInput)
                    .log();
            throw new ScmServiceException("新增盘点单失败");
        }


        LogBetter.instance(logger)
                .setLevel(LogLevel.INFO)
                .setMsg("[SCM-新增盘点单成功]")
                .addParm("统计本次所有要参与盘点的原料materialStockCodeAlls.ids",materialStockCodeAlls)
                .addParm("统计本次参与盘点失败的原料materialStockCodeFails.ids",materialStockCodeFails)
                .log();
        return true;
    }



    @Override
    public List<MaterialStockDo> findDefaultStock(String shopId) {
        return docMaterialStockManager.queryJoin4Page(shopId);
    }
}


